package org.moonlight.jvm.instructions.references.invoke;

import org.moonlight.jvm.instructions.base.MethodInvokeLogic;
import org.moonlight.jvm.rtda.exclusive.Frame;
import org.moonlight.jvm.rtda.share.heap.Class;
import org.moonlight.jvm.rtda.share.heap.classmember.Method;
import org.moonlight.jvm.rtda.share.heap.symref.MethodRef;
import org.moonlight.jvm.rtda.share.methodarea.RtConstantPool;

/**
 * invoke_static指令: 执行静态方法
 *
 * @author Moonlight
 * @createTime 2023/9/12 14:35
 **/
public class InvokeStatic extends MethodInvokeLogic {

    @Override
    public void execute(Frame frame) {
        RtConstantPool rtCp = frame.getMethod().getClazz().getRtCp();
        MethodRef methodRef = (MethodRef) rtCp.getConstant(this.idx);
        Method m = methodRef.resolvedMethod();
        Class clazz = m.getClazz();
        // 如果类还没有经过类初始化，那么需要先经过类初始化
        // 类初始化时，先终止当前指令的执行，并将当前栈帧的nextPc重置指向当前指令
        if (!clazz.isInitStarted()) {
            frame.revertNextPc();
            clazz.classInit(frame.getThread());
            return;
        }
        // 假定解析符号引用后得到方法M。M必须是静态方法，否则抛出Incompatible-ClassChangeError异常。
        // M不能是类初始化方法。类初始化方法只能由Java虚拟机调用，不能使用invokestatic指令调用。
        // 这一规则由class文件验证器保证，这里不做检查。如果声明M的类还没有被初始化，则要先初始化该类。
        if (!m.isStatic()) {
            throw new IncompatibleClassChangeError();
        }
        invokeMethod(frame, m);
    }

}
